/*
 * 处理 cvecs 的工具函数
 * 此文件由 regcomp.c 包含。
 *
 * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
 *
 * 本软件的开发部分由 Cray Research Inc.、UUNET Communications Services Inc.、Sun Microsystems Inc. 和 Scriptics Corporation 资助， 他们都不对结果负责。作者对他们表示感谢。
 *
 * Redistribution and use in source and binary forms -- with or without
 * modification -- are permitted for any purpose, provided that
 * redistributions in source form retain this entire copyright notice and
 * indicate the origin and nature of any modifications.
 *
 * I'd appreciate being given credit for this package in the documentation
 * of software which uses it, but that is not a requirement.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * src/backend/regex/regc_cvec.c
 *
 */

/*
 * 注意：
 * 只有（选定的）函数在 _这个_ 文件中应该将 cvec 的 chr 数组视为非常量。
 */

/*
 * newcvec - 分配一个新的 cvec
 */
static struct cvec * newcvec(int fc_nchrs,				/* 用于持有这么多字符... */
		int fc_nranges)			/* ... 和这么多范围 */
{
	size_t		fc_nc = (size_t) fc_nchrs + (size_t) fc_nranges * 2;
	size_t		fc_n = sizeof(struct cvec) + fc_nc * sizeof(chr);
	struct cvec *fc_cv = (struct cvec *) MALLOC(fc_n);

	if (fc_cv == NULL)
		return NULL;
	fc_cv->chrspace = fc_nchrs;
	fc_cv->chrs = (chr *) (((char *) fc_cv) + sizeof(struct cvec));
	fc_cv->ranges = fc_cv->chrs + fc_nchrs;
	fc_cv->rangespace = fc_nranges;
	return clearcvec(fc_cv);
}

/*
 * clearcvec - 清除一个可能的新 cvec
 * 返回指针以方便使用。
 */
static struct cvec * clearcvec(struct cvec *fc_cv)
{
	assert(fc_cv != NULL);
	fc_cv->nchrs = 0;
	fc_cv->nranges = 0;
	fc_cv->cclasscode = -1;
	return fc_cv;
}

/*
 * addchr - 向 cvec 添加一个字符
 */
static void addchr(struct cvec *fc_cv,			/* 字符向量 */
	   chr fc_c)					/* 要添加的字符 */
{
	assert(fc_cv->nchrs < fc_cv->chrspace);
	fc_cv->chrs[fc_cv->nchrs++] = fc_c;
}

/*
 * addrange - 向 cvec 添加一个范围
 */
static void addrange(struct cvec *fc_cv,		/* 字符向量 */
		 chr fc_from,				/* 范围的第一个字符 */
		 chr fc_to)				/* 范围的最后一个字符 */
{
	assert(fc_cv->nranges < fc_cv->rangespace);
	fc_cv->ranges[fc_cv->nranges * 2] = fc_from;
	fc_cv->ranges[fc_cv->nranges * 2 + 1] = fc_to;
	fc_cv->nranges++;
}

/*
 * getcvec - 获取一个瞬态 cvec，初始化为空
 *
 * 返回的 cvec 仅在下一个 getcvec 调用之前有效，通常会回收此空间。调用者**不应该**显式释放 cvec；当结构变量被销毁时，它将被清理。
 *
 * 这通常用于解析括号表达式。在该使用中，cvec 仅在我们从中构建弧时暂时需要，因此瞬态性是一种方便的行为。
 */
static struct cvec * getcvec(struct vars *v,			/* 设置 */
		int fc_nchrs,				/* 用于持有这么多字符... */
		int fc_nranges)			/* ... 和这么多范围 */
{
	/* 如果足够大，则回收现有的瞬态 cvec */
	if (v->cv != NULL && fc_nchrs <= v->cv->chrspace &&
		fc_nranges <= v->cv->rangespace)
		return clearcvec(v->cv);

	/* 不，创建一个新的 */
	if (v->cv != NULL)
		freecvec(v->cv);
	v->cv = newcvec(fc_nchrs, fc_nranges);
	if (v->cv == NULL)
		ERR(REG_ESPACE);

	return v->cv;
}

/*
 * freecvec - 释放一个 cvec
 */
static void freecvec(struct cvec *fc_cv)
{
	FREE(fc_cv);
}
